﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NumericalData.DifferentialEquations.Methods.Felberg.Constants
{
    abstract public class FelbergConstants
    {
        protected double[] _alphas;
        protected double[][] _bettas;
        protected double[] _parameters;

        public FelbergConstants(){}

        public double? GetAlpha(int index)
        {
            try
            {
                return _alphas[index - 1];
            }
            catch
            {
                return null;
            }
        }

        public double? GetBetta(int firstIndex, int secondIndex)
        {
            try
            {
                return _bettas[firstIndex - 1][secondIndex - 1];
            }
            catch
            {
                return null;
            }
        }

        public double? GetParameter(int index)
        {
            try
            {
                return _parameters[index - 1];
            }
            catch
            {
                return null;
            }
        }
    }

    public class SevenOrderConstants : FelbergConstants
    {
        public SevenOrderConstants()
        {
            _alphas = new[] {0, 2.0/27, 1.0/9, 1.0/6, 5.0/12, 1.0/2, 5.0/6, 1.0/6, 2.0/3, 1.0/3, 1, 0, 1};
            _bettas = new[]
                          {
                              new double[] {0}, //1
                              new[] {2.0/27}, //2
                              new[] {1.0/36, 1.0/12}, //3
                              new[] {1.0/24, 0, 1.0/8}, //4 
                              new[] {5.0/12, 0, -25.0/16, 25.0/16}, //5 
                              new[] {1.0/20, 0, 0, 1.0/4, 1.0/5}, //6
                              new[] {-25.0/108, 0, 0, 125.0/108, -65.0/27, 125.0/54}, //7
                              new[] {32.0/300, 0, 0, 0, 61.0/225, -2.0/9, 13.0/900}, //8 
                              new[] {2.0, 0, 0, 23.0/108, 704.0/45, -107.0/9, 67.0/90, 3.0}, //9
                              new[] {-91.0/108, 0, 0, 23.0/108, -976.0/135, 311.0/54, -19.0/60, 17.0/6, -1.0/12}, //10
                              new[]
                                  {
                                      2383.0/4100, 0, 0, -341.0/164, 4496.0/1025, -301.0/82, 2133.0/4100, 45.0/82, 45.0/164
                                      , 18.0/41
                                  },
                              //11 
                              new[] {3.0/205, 0, 0, 0, 0, -6.0/41, -3.0/205, -3.0/41, 3.0/41, 6.0/41, 0}, //12 
                              new[]
                                  {
                                      -1777.0/4100, 0, 0, -341.0/164, 4496.0/1025, -289.0/82, -2193.0/4100, 51.0/82,
                                      33.0/164, 12.0/41, 0,
                                      1.0
                                  } //13 
                          };
            _parameters = new[] {41.0/840, 0, 0, 0, 0, 34.0/105, 9.0/35, 9.0/35, 9.0/280, 9.0/280, 41.0/840, 0, 0};
        }
    }

    public class EightOrderConstants : SevenOrderConstants
    {
        public EightOrderConstants() :base()
        {
            _parameters = new double[] {0, 0, 0, 0, 0, 34.0/105, 9.0/35, 9.0/35, 9.0/280, 9.0/280, 41.0/840, 0, 0};
        }
    }
}
